<template>
  <div class="relative">
    <div id="ali-player" class="min-h-52 overflow-hidden object-cover z-10">
      <div v-if="slotVisible" class="absolute z-30 inset-0 right-0 bottom-0 text-base text-white font-bold">
        <slot name="main"></slot>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { PropType, watch } from "vue";
const instance = ref(null); // 播放器实例
const slotVisible = ref(false); // 插槽是否显示
const props = defineProps({
  vid: {
    // 媒体视频vid
    type: String,
    default: "",
  },
  playauth: {
    // 播放凭证
    type: String,
    default: "",
  },
  isLive: {
    // 是否直播
    type: Boolean,
    default: false,
  },
  seek: {
    // 跳转到某个时间点
    type: Number,
    default: 0,
  },
  source: {
    // 视频源  优先级：视频源 > vid + playauth
    type: String,
    default: "",
  },
  cover: {
    // 封面 URL
    type: String,
    default: "",
  },
  progressMarkers: {
    // 进度条上的标记点
    type: Array,
    default: () => [],
  },
  showBarTime: {
    // 多少毫秒自动隐藏底部控制栏
    type: String,
    default: "2000",
  },
  autoplay: {
    // 是否自动播放
    type: Boolean,
    default: false,
  },
  width: {
    // 宽度
    type: String,
    default: "100%",
  },
  height: {
    // 高度
    type: String,
    default: "200px",
  },
  controlVisible: {
    // 控制栏显示
    type: String as PropType<"click" | "hover" | "always" | "never">,
    default: "hover",
  },
  bulletScreenConfig: {
    // 视频跑马灯配置 -- 防盗链
    type: Object as PropType<{
      text: String;
      style: Object;
      position: "random" | "top" | "bottom";
    }>,
    default: () => ({}),
  },
  freeTime: {
    // 免费观看时长
    type: Number,
    default: 0,
  },
  seekPointList: { // [offset: 20, text: '']
    // 跳转节点列表
    type: Array,
    default: () => [],
  },
  timePointList: {
    // 时间节点(以秒数为单位)，用于答题互动，到达某一个时间节点后，向父组件推送一个事件reachPoint
    type: Array,
    default: () => [],
  },
  // SDK 需要的远程资源
  cssLink: {
    required: false,
    type: String,
    default:
      "https://g.alicdn.com/apsara-media-box/imp-web-player/2.16.3/skins/default/aliplayer-min.css",
  },
  scriptSrc: {
    required: false,
    type: String,
    default:
      "https://g.alicdn.com/apsara-media-box/imp-web-player/2.16.3/aliplayer-h5-min.js",
  },
  scriptComponent: {
    required: false,
    type: String,
    default: "./src/assets/aliplayercomponents-1.0.9.min.js",
  },
});
let ListComponent = null
const emits = defineEmits(["previewEnd", "reachPoint", "ended", "saveTime"]);

// 隐藏列表遮罩
const hideListMask = () => {
  let dom = document.querySelector('.list-mask')
  dom && dom.classList.add('hidden')
}


// 播放源变化，重新初始化播放器
watch(
  () => props.source,
  (val) => {
    dispose();
    instance.value = null;
    if (val) {
      initComponent()
      initPlayer();
      hideListMask()
    }

  }
);

// 更新试看时长的变化
watch(
  () => props.freeTime,
  (val) => {
    instance.value.setPreviewTime(val);
  }
);

// 更新视频封面的变化
watch(
  () => props.cover,
  (val) => {
    instance.value.setCover(val);
  }
);

// 注册web端阿里云播放器SDK
const insertScript = () => {
  const linkID = "aliplayer-css";
  const scriptID = "aliplayer-script";
  const scriptComponentID = "aliplayer-script-component";
  let linkIDTag = document.getElementById(linkID);
  let scriptIDTag = document.getElementById(scriptID);
  let scriptComponentIDTag = document.getElementById(scriptComponentID);
  const head = document.getElementsByTagName("head");
  let count = 0;
  const requestCount = () => {
    if (count >= 2) {
      initComponent()
      initPlayer();

    } else {
      count++;
    }
  };

  if (!linkIDTag) {
    const link = document.createElement("link");
    link.type = "text/css";
    link.rel = "stylesheet";
    link.href = props.cssLink;
    link.id = linkID;
    head[0].appendChild(link);
    link.onload = () => {
      requestCount();
    };
  }
  if (!scriptIDTag) {
    const script = document.createElement("script");
    script.type = "text/javascript";
    script.src = props.scriptSrc;
    script.id = scriptID;
    head[0].appendChild(script);
    script.onload = () => {
      requestCount();
    };
  }
  if (!scriptComponentIDTag) {
    const scriptComponent = document.createElement("script");
    scriptComponent.type = "text/javascript";
    scriptComponent.src = props.scriptComponent;
    scriptComponent.id = scriptComponentID;
    head[0].appendChild(scriptComponent);

    scriptComponent.onload = () => {
      requestCount();
    };
  }
};

// 初始化阿里云自定义组件
const initComponent = () => {
  ListComponent = Aliplayer.Component({
    hideEle: function () {
      // 隐藏列表遮罩
      this.DOMNode.classList.add('translate-x-full')
    },
    init: function (data) {
      this.data = data;
      this.DOMNode = null;
      this.DOMNodeList = null;
    },
    createEl: function (el) {
      console.log(1);

      let data = this.data
      let div = document.createElement("div");
      div.innerHTML = '目录';
      div.style = 'float: right; margin-right: 5px; margin-top: 13px; color: #fff; font-size: 1rem;'
      if (!this.DOMNodeList && !this.DOMNode) {
        this.DOMNode = document.createElement('div')
        this.DOMNode.classList.add('absolute', 'inset-0', 'z-30', 'text-base', 'text-white', 'transition', 'ease-in', 'translate-x-full', 'duration-300')
        this.DOMNodeList = document.createElement('div')
        this.DOMNodeList.classList.add('py-2', 'absolute', 'z-50', 'top-0', 'bottom-0', 'right-0', 'w-2/5', 'text-base', 'text-white', 'bg-dark-50', 'opacity-50', 'overflow-y-auto')
        this.DOMNode.appendChild(this.DOMNodeList)
        document.querySelector('#ali-player').appendChild(this.DOMNode)
        this.DOMNode.addEventListener('click', function (e) {
          this.classList.add('translate-x-full')
        })
      }
      // 点击目录添加事件
      div.onclick = () => {
        if (this.DOMNodeList.children.length != data.length) {
          const frag = document.createDocumentFragment()
          data.forEach(item => {
            let li = document.createElement('div')
            li.classList.add('overflow-hidden', 'text-md', 'text-white', 'transition', 'hover:text-blue-300', 'flex', 'item-center')
            li.innerHTML = `<svg t="1692776312499" class="icon w-10 basis-5" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1083" width="30" height="25"><path d="M234.624 864A129.344 129.344 0 0 1 96 746.688V277.376A129.344 129.344 0 0 1 234.624 160h554.688A129.344 129.344 0 0 1 928 277.376v469.312a129.344 129.344 0 0 1-138.688 117.312z m-41.6-586.624v469.312a38.848 38.848 0 0 0 41.6 35.136h554.688a38.784 38.784 0 0 0 41.6-35.136V277.376a38.912 38.912 0 0 0-41.6-35.264H234.624a38.912 38.912 0 0 0-41.6 35.264z m152.128 369.472V377.152a51.2 51.2 0 0 1 76.8-44.224l231.168 134.848a50.496 50.496 0 0 1 25.6 44.224 50.432 50.432 0 0 1-25.6 44.096l-231.168 134.976a50.816 50.816 0 0 1-25.6 7.04 51.2 51.2 0 0 1-51.2-51.264z m76.8-44.8l154.752-90.24-154.752-90.304z" fill="#ffffff" fill-opacity="0.9" p-id="1084"></path></svg> <div class="flex-1 truncate">${item.text}</div>`
            frag.appendChild(li)
          })
          this.DOMNodeList.appendChild(frag)
        }

        Array.from(this.DOMNode.classList).includes('translate-x-full') ? this.DOMNode.classList.remove('translate-x-full') : this.DOMNode.classList.add('translate-x-full')

        // 列表遮罩的事件委托
        this.DOMNodeList.addEventListener('click', function (e) {
          const target = e.target
          const index = Array.from(target.parentNode.children).indexOf(target)
          instance.value.seek(data[index].offset)
          e.stopPropagation()
        })

      }
      // 控制条挂载当前组件
      const controlBar = document.querySelector('.prism-controlbar');
      controlBar.appendChild(div);
    },
    play(player, e) {
      this.hideEle()
    },
    ended(player, e) {
      this.hideEle()
    },
    dispose(player, e) {
      this.hideEle()
      this.DOMNode = null
      this.DOMNodeList = null
    }
  });
}

// 阿里云记忆组件参数方法集成
const getTime = () => {
  return props.seek
}
const saveTime = function (memoryVideo, currentTime) {
  emits("saveTime", memoryVideo, currentTime)
}

// 初始化播放器
const initPlayer = () => {
  instance.value = new Aliplayer(
    {
      id: "ali-player",
      width: props.width,
      height: props.height,
      source: props.source,
      isLive: props.isLive,
      autoplay: props.autoplay,
      preload: true,
      showBarTime: "2000",
      controlBarVisibility: props.controlVisible,
      vid: props.vid,
      playauth: props.playauth,
      cover: props.cover,
      progressMarkers: props.progressMarkers,
      components: [
        {
          name: "BulletScreenComponent",
          type: AliPlayerComponent.BulletScreenComponent,
          args: [
            props.bulletScreenConfig.text,
            props.bulletScreenConfig.style,
            props.bulletScreenConfig.position,
          ],
        },
        {
          name: "PreviewVodComponent",
          type: AliPlayerComponent.PreviewVodComponent,
          args: [
            props.freeTime,
            `<div class="h-full w-full flex justify-center items-center" id="previewEnd">试看已结束</div>`,
            `请购买在观看完整视频`,
          ],
        },
        { name: 'ListComponent', type: ListComponent, args: [props.seekPointList] },
        {
          name: 'MemoryPlayComponent',
          type: AliPlayerComponent.MemoryPlayComponent,
          args: [false, getTime, saveTime]
        }
      ],
    },
    function (player) {
      // 记忆进度
      if (props.seek) {
        player.seek(props.seek)
      }
      // 点击试看结束DOM元素，挂载点击事件
      document
        .getElementById("previewEnd")
        .addEventListener("click", previewEnd);
      // 监听播放进度
      player.on("timeupdate", handleAnswer);
      player.on("ended", () => {
        document.querySelector('.prism-big-play-btn').style = 'position: absolute; left: 30px; bottom: 80px; display: none;'
        emits("ended")
      })
    }
  );
};

// 试看结束监听事件
const previewEnd = () => {
  // 关闭遮罩层
  document.querySelector(".preview-component-layer").style.display = "none";
  instance.value.seek(0);
  slotVisible.value = false;
  // 向父组件暴露事件
  emits("previewEnd");
};

// 播放器播放进度监听事件
const handleAnswer = () => {
  let currTime = Math.ceil(instance.value.getCurrentTime());
  if (currTime == handleAnswer.reachPoint) return;
  if (!props.timePointList.length) return;
  let pointIndex = 0;

  // 如果传入了时间节点，触发以下事件
  if (props.timePointList && props.timePointList.length > 0) {
    let timePoint = props.timePointList.find((item, index) => {
      pointIndex = index;
      return currTime == item;
    });
    if (timePoint) {
      // 触发时间节点事件
      handleAnswer.reachPoint = props.timePointList[pointIndex]; // 记录到达时间的节点（秒）
      // instance.value.pause();
      // slotVisible.value = true;
      emits("reachPoint", props.timePointList[pointIndex]);
    }
  }
};

// 分钟：秒 格式 转换成秒
const convertToSeconds = (time) => {
  const [minutes, seconds] = time.split(":");
  return parseInt(minutes) * 60 + parseInt(seconds);
};

// 播放器播放
const play = () => {
  let mask = document.querySelector(".preview-component-layer")
  if (mask) {
    document.querySelector(".preview-component-layer").style.display = "none";
  }
  instance.value && instance.value.play();
};

// 播放器暂停
const pause = () => {
  instance.value && instance.value.pause();
};

// 播放器销毁
const dispose = () => {
  // 移除试看结束后，试看DOM元素的监听事件
  let previewMask = document.getElementById("previewEnd")
  if (previewMask) {
    previewMask.removeEventListener("click", previewEnd);
  }
  instance.value.off("timeupdate", handleAnswer);
  instance.value && instance.value.dispose();
};

// 控制插槽是否显示
const toggleSlotVisible = (status) => {
  slotVisible.value = status;
};

// 控制视频播放进度
const seek = (time) => {
  instance.value && instance.value.seek(time);
};

// 获取视频当前播放进度
const getPercentage = () => {
  return instance.value && (parseFloat((instance.value.getCurrentTime() / instance.value.getDuration()).toFixed(3))) * 100;
};

// 处理继续答题
const continueAswer = () => {
  instance.value && instance.value.on("timeupdate", handleAnswer);
  play();
};
onMounted(() => {
  if (!window.Aliplayer) {
    insertScript();
  } else {
    initComponent()
    initPlayer();
  }
});


defineExpose({ play, pause, continueAswer, getPercentage, dispose, toggleSlotVisible, seek });
</script>

<style lang="scss" scoped>
.list {
  &::-webkit-scrollbar {
    width: 0px;
    height: 0px;
  }
}
</style>

